import 'reflect-metadata';

export const RequestMethod = {
    GET: 'get',
    POST: 'post',
    PUT: 'put',
    PATCH: 'patch',
    DELETE: 'delete',
    OPTION: 'option'
}

export enum RequestMethodEnum {
    GET = 'get',
    POST = 'post',
    PUT = 'put',
    PATCH = 'patch',
    DELETE = 'delete',
    OPTION = 'option'
}

export type MethodType = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'option';

export interface RequestParam {
    url: string;
    middlewares?: any[];
}

export enum DecoratorKey {
    Controller = "controller",
    Method = "method",
    Param = "param",
    Body = "body"
}

export interface MethodMetadata {
    method: RequestMethodEnum;
    url: string;
    middleware: any[];
    fn: Function;
}

export const controller = ({ prefix }: { prefix: string }) => (target: any) => {
    Reflect.defineMetadata(DecoratorKey.Controller, prefix, target);
};

export const methodDefine = (methodType: RequestMethodEnum) =>
    (requestParam: RequestParam) => {
        return (target: any, name: string, descriptor: PropertyDescriptor) => {
            Reflect.defineMetadata(
                DecoratorKey.Method,
                {
                    method: methodType,
                    url: requestParam.url,
                    middleware: requestParam.middlewares,
                    fn: descriptor.value,
                },
                target,
                name
            );
        }
    }

export const get = methodDefine(RequestMethodEnum.GET);
export const post = methodDefine(RequestMethodEnum.POST);
export const put = methodDefine(RequestMethodEnum.PUT);
export const patch = methodDefine(RequestMethodEnum.PATCH);
export const del = methodDefine(RequestMethodEnum.DELETE);
